package foundation.SurModel;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import abstractGA.result.ChangeElem;
import abstractGA.result.OneOpt;
import algorithm.SAElem;
import control.ExeCtx;
import control.PerfEvaluator;
import control.RelbEvaluator;
import control.SAModifier;
import control.ms.MSCtrlEngine;
import control.ste.STECtrlEngine;
import foundation.pcmUtil.RptFileHelper;
import plan.InitiExeCtx;

/**
 * Simple algorithm to generate Latin-hypercube sampling
 *
 */
public class SimpleLH {
	STECtrlEngine STEEngine = null;
	public SimpleLH() {
		String srcPath = "demo/ste/runfiles/initialSA/";
		String basePath = "demo/ste/runfiles/resultFile/";
		String caseName = "ste";
		String UsageScenarioProer = "UsageScenario_Graphical only Usage Scenario_1_Processor";
		String reltFilePath = "demo/ste/runFiles/resultFile/reliabilityRlt.markovresult";
		String algCfgFileName = "demo/ste/cfgFiles/NSRulSeqGAConf.properties";
		String rulCfgFlNm = "demo/ste/cfgFiles/ruleConfig.properties";
		ArrayList<Integer> strtIdxs = new ArrayList<Integer>();// 处理器速度、组件部署和组件选择的起始下标
		String reltRptFlNm = null;// 可靠性报告文件名
//		RulExeCtx exeCtx = new RulExeCtx(srcPath, basePath, caseName, UsageScenarioProer, reltFilePath, algCfgFileName,
//				rulCfgFlNm);
//
//		JssBRSRulSeqCtrlEngHlper hlper = new JssBRSRulSeqCtrlEngHlper(exeCtx);
		String prefix = "default";
		String algName = "DFGA";
		InitiExeCtx initiExeCtx = new InitiExeCtx();
		ExeCtx exeCtx=initiExeCtx.getInitCtx(caseName, prefix, algName);
		SAModifier sAModifier =new SAModifier(exeCtx);
		PerfEvaluator perfEvaluator = new PerfEvaluator(exeCtx);
		RelbEvaluator relbEvaluator = new RelbEvaluator(exeCtx);
		STEEngine = new STECtrlEngine(exeCtx, sAModifier,perfEvaluator, relbEvaluator);
	}

	/**
	 * Generate matrix (nSamples x nDim) so that each column is a permutation of
	 * 1->N
	 * 
	 * @param N
	 *            Number of samples
	 * @param dim
	 *            Number of dimensions
	 */
	public int[][] getSimpleLH(int N, int dim) {
		int[][] LH = new int[N][dim];
		for (int c = 0; c < dim; c++) {
			int[] perm = getPerm(N);
			for (int r = 0; r < N; r++) {
				LH[r][c] = perm[r];
			}
		}
		return LH;
	}

	/**
	 * Get permutation from 1:N
	 * 
	 * @param N
	 * @return Array of permutated indices from 1 to N
	 */
	public int[] getPerm(int N) {
		int[] res = new int[N];
		int i, k;
		// initialization
		for (i = 0; i < N; i++)
			res[i] = i + 1;
		// permutation
		for (i = 0; i < N - 1; i++) {
			k = i + (int) (Math.random() * (N - i));
			int temp = res[i];
			res[i] = res[k];
			res[k] = temp;
		}
		return res;
	}

	public List<List<StringBuffer>> getCodesByLH(int simpNum) {
		List<List<StringBuffer>> codes = new ArrayList<List<StringBuffer>>();

		// 获取LH样本
		int[][] aLHExples = getSimpleLH(simpNum, 7);

		// 解析
		for (int i = 0; i < simpNum; i++) {
			List<StringBuffer> code = new ArrayList<StringBuffer>();
			for (int j = 0; j < 7; j++) {
				// 生成4个处理器速度,每个都在5.0-20.0之间
				if (j < 3) {
					float procSpd = 2f + (6f / simpNum) * aLHExples[i][j];
					System.out.println(procSpd);
					StringBuffer spd = new StringBuffer(String.valueOf(procSpd));
					code.add(spd);
				}

				// 生成9个server的名字
				if ((j >= 3) && (j <6 )) {
					int srvNum = 1 + (int) Math.round((2f / simpNum) * aLHExples[i][j]);
					String srvName="";
					switch (srvNum) {
					case 1:
						srvName = "server1";
						break;
					case 2:
						srvName = "server2";
						break;
					case 3:
						srvName = "server3";
						break;
					default:
						break;
					}
					StringBuffer serverName = new StringBuffer(srvName);
					code.add(serverName);
				}
				// 组件选择

				if (j==6) {// 第2个组件选择
					int val = aLHExples[i][j];
					int thrVal = (int) Math.round(simpNum / 2f);
					if (val <= thrVal) {
						code.add(new StringBuffer("QuickBooki"));
					} else {
						code.add(new StringBuffer("BookingSyst"));
					}
				}

			}
            if(!STEEngine.isLegalCodes(code)){
            	code=STEEngine.repairCodes(code);
            }
            codes.add(code);
		}
		return codes;
	}
	public STECtrlEngine getSTEEngine() {
		return STEEngine;
	}

	public void setSTEEngine(STECtrlEngine STEEngine) {
		this.STEEngine = STEEngine;
	}

	/**
	 * @param args
	 */
	public static void insertDataToTempRunTable(int dataNums) {
		SimpleLH simLH=new SimpleLH();
		SMDAO  dao=new SMDAO();
///////////////////////////////////
		String rltPath = "demo/ste/runFiles/resultFile";
		
		RptFileHelper rptHlp=null;
		STECtrlEngine STEEngine =simLH.getSTEEngine();
		//按LHS方法采样
//		List<List<StringBuffer>> codes = new ArrayList<List<StringBuffer>>();
//		List<StringBuffer> oneCode = new ArrayList<>();
//		for(int i=0;i<1000;i++){
//			oneCode = jssBrsEngine.getRndCodes();
//			codes.add(oneCode);
//		}
		List<List<StringBuffer>> codes=simLH.getCodesByLH(dataNums);
        //求解适应度值
		int opti = 1;
		//UUID uuid = UUID.randomUUID();// GUID
		String runID = "!!SMDFGA";//+ uuid.toString();
		
		for (List<StringBuffer> code : codes) {
			ArrayList<Float> objVals=STEEngine.getObjVals(code);
			
			SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 设置日期格式
			OneOpt oneOpt = new OneOpt();
			oneOpt.setRunID(runID);
			oneOpt.setGenID("1");
			oneOpt.setOptID(String.valueOf(opti++));
			oneOpt.setRunTime(df.format(new Date()));
			oneOpt.setcode(code.toString());
			oneOpt.setRestValue(objVals.get(0));
			oneOpt.setReltValue(objVals.get(1));
			oneOpt.setCostValue(objVals.get(2));

			// 配置变更元素
			ArrayList<ChangeElem> chgElems = new ArrayList<ChangeElem>();
			ArrayList<SAElem> chgSAElems = STEEngine.getChgedElems(code);
			for (SAElem saElem : chgSAElems) {
				ChangeElem changeElem = new ChangeElem();
				changeElem.setDoFID(saElem.getDoFID());
				changeElem.setElemName(saElem.getElemName());
				changeElem.setValue(saElem.getValue());
				chgElems.add(changeElem);
			}
			oneOpt.setChgElems(chgElems);
			dao.addAlgRun3(oneOpt);
			
			/***********************
			 * 
			 * 请李松增加代码完成：(1)根据编码获取处理器名列表；（2）获取最大使用率处理器的名字及其所对应使用率
			 */
//			float maxPUtil=0f;//最高使用率
//			String pNmOfMaxUtil="";//最高使用率对应处理器的名称
//			
//			//根据编码获取处理器名列表
//			ArrayList<String> fileNms = TxtFileUtil.findFileNms(rltPath, ".out.lqxo");
//			int size = fileNms.size();
//			String rptFileNm = rltPath+"/"+fileNms.get(size - 1);
//			rptHlp = new RptFileHelper(rptFileNm);
//			//获取当前SA中server的CPU解析成的processor
//			List<String> proNames = rptHlp.getUsedProcesssors();	
//			//获取最大使用率的server名字
//			pNmOfMaxUtil=rptHlp.getMaxUtilSvr(proNames);
//			maxPUtil = rptHlp.getSvrUtil(pNmOfMaxUtil);
//			//pNmOfMaxUtil
//			PefIdx pefIdx=new PefIdx();
//			
//			 pefIdx.setRunID(runID);// 算法运行标识
//			 pefIdx.setGenID("1");// 演化代数
//			 pefIdx.setOptID(String.valueOf(opti));// 优化次数
//			 pefIdx.setParaTypeNm("maxPUtil");//参数类型
//			 pefIdx.setElemName(pNmOfMaxUtil);// 元素名称
//			 pefIdx.setParaValue(maxPUtil);// 值
//			
////			 dao.addPefIdx(pefIdx);
//			 
//			 
//			 try {
//					Thread.sleep(2 * 1000);
//				} catch (InterruptedException e) {
//					e.printStackTrace();
//				}
//			opti++;
		}
	}

}
